/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */
#include "screenlock.h"
#include "ui_screenlock.h"
#include "bgfileparse.h"
#include "pictureunit.h"
#include "widgets/MaskWidget/maskwidget.h"

#include <QDebug>
#include <QDir>
#include <QFileDialog>
#include <QDesktopServices>
#include <sys/stat.h>

#define BGPATH                  "/usr/share/backgrounds/"
#define SCREENLOCK_BG_SCHEMA    "org.ukui.screensaver"
#define SCREENLOCK_BG_KEY       "background"
#define SCREENLOCK_DELAY_KEY    "idle-lock"
#define SCREENLOCK_LOCK_KEY     "lock-enabled"
#define SCREENLOCK_ACTIVE_KEY   "idle-activation-enabled"

#define MATE_BACKGROUND_SCHEMAS "org.mate.background"
#define FILENAME                "picture-filename"
#define DEFAULT_LOCK "/usr/share/backgrounds/1-openkylin.jpg"
#define DEFAULT_LOCK_2 "/usr/share/backgrounds/openkylin.jpg"

const QString kylinUrl        = "https://www.ubuntukylin.com/wallpaper.html";

Screenlock::Screenlock() : mFirstLoad(true)
{
    pluginName = tr("Screenlock");
    pluginType = PERSONALIZED;
    prePicUnit = nullptr;
    pWorker = nullptr;
    pThread = nullptr;
}

Screenlock::~Screenlock()
{
    if (pWorker) {
        pWorker->setExit(true);
    }
    if (pThread) {
        pThread->quit(); // 退出事件循环
        pThread->wait(); // 释放资源
    }
    if (!mFirstLoad) {
        delete ui;
        ui = nullptr;
    }
}

QString Screenlock::plugini18nName()
{
    return pluginName;
}

int Screenlock::pluginTypes()
{
    return pluginType;
}

QWidget *Screenlock::pluginUi()
{
    if (mFirstLoad) {
        mFirstLoad = false;

        ui = new Ui::Screenlock;
        pluginWidget = new QWidget;
        pluginWidget->setAttribute(Qt::WA_DeleteOnClose);
        ui->setupUi(pluginWidget);

        ui->titleLabel->setStyleSheet(" QLabel{color: palette(windowText);}");

        const QByteArray id(SCREENLOCK_BG_SCHEMA);
        lSetting = new QGSettings(id, QByteArray(), this);

        connectToServer();
        initSearchText();
        setupComponent();
        setupConnect();
        initScreenlockStatus();

        lockbgSize = QSize(400, 240);
        if (isIntel()) {
            settingForIntel();
        }
    } else {
        ui->backgroundsWidget->resize(ui->backgroundsWidget->size() - QSize(1,1));
        ui->backgroundsWidget->resize(ui->backgroundsWidget->size() + QSize(1,1));
    }
    return pluginWidget;
}

const QString Screenlock::name() const
{
    return QStringLiteral("Screenlock");
}

bool Screenlock::isShowOnHomePage() const
{
    return false;
}

QIcon Screenlock::icon() const
{
    return QIcon::fromTheme("ukui-lock-screen-symbolic");
}

bool Screenlock::isEnable() const
{
    return true;
}

void Screenlock::initSearchText() {
    //~ contents_path /Screenlock/Show picture of screenlock on screenlogin
    ui->loginpicLabel->setText(tr("Show picture of screenlock on screenlogin"));
    //~ contents_path /Screenlock/Browse
    ui->browserLocalwpBtn->setText(tr("Browse"));
    //~ contents_path /Screenlock/Online Picture
    ui->onlineBtn->setText(tr("Online Picture"));
    ui->onlineBtn->setFocusPolicy(Qt::NoFocus);
    ui->onlineBtn->setContentsMargins(0,0,0,0);
    ui->onlineBtn->setCursor( QCursor(Qt::PointingHandCursor));
    ui->onlineBtn->setStyleSheet("QPushButton{background: transparent;border-radius: 4px;text-decoration: underline;} ");
    connect( ui->onlineBtn, &QPushButton::clicked, this,[=] {
        QDBusInterface ifc("com.kylin.AppManager",
                           "/com/kylin/AppManager",
                           "com.kylin.AppManager",
                           QDBusConnection::sessionBus());
        ifc.call("LaunchDefaultAppWithUrl", "https://www.ubuntukylin.com/wallpaper.html");
    });
    //~ contents_path /Screenlock/Reset To Default
    ui->resetBtn->setText(tr("Reset To Default"));
}

void Screenlock::setupComponent()
{
    mUKCConfig = QDir::homePath() + "/.config/ukui/ukui-control-center.conf";
    lockSetting = new QSettings(mUKCConfig, QSettings::IniFormat, this);

    QString name = qgetenv("USER");
    if (name.isEmpty()) {
        name = qgetenv("USERNAME");
    }

    QString lockfilename = "/var/lib/lightdm-data/" + name + "/ukui-greeter.conf";
    lockLoginSettings = new QSettings(lockfilename, QSettings::IniFormat, this);

    QStringList scaleList;
    scaleList<< tr("1min") << tr("5min") << tr("10min") << tr("30min") << tr("45min")
              <<tr("1hour") << tr("2hour") << tr("3hour") << tr("Never");

    uslider = new LockSlider(scaleList);
    uslider->setRange(1,9);
    uslider->setTickInterval(1);
    uslider->setPageStep(1);

    ui->delayFrame->layout()->addWidget(uslider);
    ui->delayFrame->hide();
    ui->line_3->hide();


    showMsgBtn = new KSwitchButton(pluginWidget);
    ui->showMsgLayout->addStretch();
    ui->showMsgLayout->addWidget(showMsgBtn);
    ui->showMsgLabel->setText(tr("Show message on lock screen"));
    ui->showMsgLabel->setVisible(false);
    showMsgBtn->setVisible(false);
    ui->line_4->setVisible(false);

    loginbgSwitchBtn = new KSwitchButton(pluginWidget);
    ui->loginbgHorLayout->addStretch();
    ui->loginbgHorLayout->addWidget(loginbgSwitchBtn);
    loginbgSwitchBtn->setChecked(getLockStatus());

    bool lockKey = false;
    QStringList keys =  lSetting->keys();

    if (keys.contains("showMessageEnabled")) {
        showMsgBtn->setChecked(lSetting->get("show-message-enabled").toBool());
        connect(showMsgBtn, &KSwitchButton::stateChanged, this, [=](bool checked){
            lSetting->set("show-message-enabled", checked);
        });
    }

    connect(lockSwitchBtn, &KSwitchButton::stateChanged, this, [=](bool checked) {
        if (lockKey) {
            lSetting->set(SCREENLOCK_LOCK_KEY,  checked);
        }
    });

    connect(lSetting, &QGSettings::changed, this, [=](QString key) {
        if ("background" == key) {
            QString filename = lSetting->get(key).toString();
            ui->previewLabel->setPixmap(QPixmap(filename).scaled(ui->previewLabel->size()));
            setClickedPic(filename);
        } else if ("idleLock" == key) {
            uslider->blockSignals(true);
            uslider->setValue(lockConvertToSlider(lSetting->get(SCREENLOCK_DELAY_KEY).toInt()));
            uslider->blockSignals(false);
        } else if ("showMessageEnabled" == key) {
            showMsgBtn->blockSignals(true);
            showMsgBtn->setChecked(lSetting->get("show-message-enabled").toBool());
            showMsgBtn->blockSignals(false);
        }
    });

    //设置布局
    flowLayout = new FlowLayout(ui->backgroundsWidget, 16, -1, -1);
}

void Screenlock::setupConnect()
{
    connect(loginbgSwitchBtn, &KSwitchButton::stateChanged, this, [=](bool checked) {
        setLockBackground(checked);
    });

    connect(uslider, &QSlider::valueChanged, [&](int value) {
        QStringList keys = lSetting->keys();
        if (keys.contains("idleLock")) {
            lSetting->set(SCREENLOCK_DELAY_KEY, convertToLocktime(value));
        }
    });

    QStringList keys = lSetting->keys();
    if (keys.contains("idleLock")) {
        int value = lockConvertToSlider(lSetting->get(SCREENLOCK_DELAY_KEY).toInt());
        uslider->setValue(value);
    }

    connect(ui->browserLocalwpBtn, &QPushButton::clicked, this, &Screenlock::setScreenLockBgSlot);
    connect(ui->resetBtn, SIGNAL(clicked(bool)), this, SLOT(resetDefaultScreenLockSlot()));
}

void Screenlock::initScreenlockStatus()
{
    // 获取当前锁屏壁纸
    QString bgStr = "";
    if (lSetting->keys().contains(SCREENLOCK_BG_KEY)) {
        bgStr = lSetting->get(SCREENLOCK_BG_KEY).toString();
    }

    // 锁屏壁纸不存在，则展示默认壁纸
    if (!QFile::exists(bgStr) || bgStr == DEFAULT_LOCK_2) {
        bgStr = DEFAULT_LOCK;
    }

    ui->previewLabel->setPixmap(QPixmap(bgStr).scaled(ui->previewLabel->size()));

    // 使用线程解析本地壁纸文件；获取壁纸单元
    pThread = new QThread;
    pWorker = new BuildPicUnitsWorker;
    connect(pWorker, &BuildPicUnitsWorker::pixmapGeneral, this, [=](QPixmap pixmap, BgInfo bgInfo){
        // 线程中构建控件传递会报告event无法install 的警告
        PictureUnit * picUnit = new PictureUnit;
        picUnit->setPixmap(pixmap);
        picUnit->setFilenameText(bgInfo.filename);

        // 选定当前锁屏壁纸
        if (bgInfo.filename == bgStr){
            if (prePicUnit != nullptr) {
                prePicUnit->changeClickedFlag(false);
                prePicUnit->setStyleSheet("border-width: 0px;");
            }
            picUnit->changeClickedFlag(true);
            prePicUnit = picUnit;
            picUnit->setFrameShape(QFrame::Box);
            picUnit->setStyleSheet(picUnit->clickedStyleSheet);
        }

        connect(picUnit, &PictureUnit::clicked, [=](QString filename){
            if (prePicUnit != nullptr) {
                prePicUnit->changeClickedFlag(false);
                prePicUnit->setStyleSheet("border-width: 0px;");
            }
            picUnit->changeClickedFlag(true);
            prePicUnit = picUnit;
            picUnit->setFrameShape(QFrame::Box);
            picUnit->setStyleSheet(picUnit->clickedStyleSheet);
            ui->previewLabel->setPixmap(QPixmap(filename).scaled(ui->previewLabel->size()));
            if (lSetting->keys().contains(SCREENLOCK_BG_KEY))
                lSetting->set(SCREENLOCK_BG_KEY, filename);
            setLockBackground(loginbgSwitchBtn->isChecked());
        });

        flowLayout->addWidget(picUnit);
    });
    connect(pWorker, &BuildPicUnitsWorker::workerComplete, [=]{
        pThread->quit(); // 退出事件循环
        pThread->wait(); // 释放资源
    });

    pWorker->moveToThread(pThread);
    connect(pThread, &QThread::started, pWorker, &BuildPicUnitsWorker::run);
    connect(pThread, &QThread::finished, this, [=] {

    });
    connect(pThread, &QThread::finished, pWorker, &BuildPicUnitsWorker::deleteLater);

    pThread->start();

    // 设置锁屏时间，屏保激活后多久锁定屏幕
    int lDelay = 0;
    if (lSetting->keys().contains("idleLock")) {
        lDelay = lSetting->get(SCREENLOCK_DELAY_KEY).toInt();
    }

    uslider->blockSignals(true);
    uslider->setValue(lockConvertToSlider(lDelay));
    uslider->blockSignals(false);
}

int Screenlock::convertToLocktime(const int value)
{
    switch (value) {
    case 1:
        return 1;
        break;
    case 2:
        return 5;
        break;
    case 3:
        return 10;
        break;
    case 4:
        return 30;
        break;
    case 5:
        return 45;
        break;
    case 6:
        return 60;
        break;
    case 7:
        return 120;
        break;
    case 8:
        return 180;
        break;
    case 9:
        return -1;
        break;
    default:
        return -1;
        break;
    }
}

int Screenlock::lockConvertToSlider(const int value)
{
    switch (value) {
    case 1:
        return 1;
        break;
    case 5:
        return 2;
        break;
    case 10:
        return 3;
        break;
    case 30:
        return 4;
        break;
    case 45:
        return 5;
        break;
    case 60:
        return 6;
        break;
    case 120:
        return 7;
        break;
    case 180:
        return 8;
        break;
    case -1:
        return 9;
        break;
    default:
        return 9;
        break;
    }
}

//设置登录界面显示锁屏壁纸
void Screenlock::setLockBackground(bool status)
{
    QString bgStr;
    struct stat fileStat;
    if (lSetting && status && lSetting->keys().contains(SCREENLOCK_BG_KEY)) {
        bgStr = lSetting->get(SCREENLOCK_BG_KEY).toString();
        stat(bgStr.toStdString().c_str(),&fileStat);
        if (fileStat.st_uid != 0) {  //在普通用户下
            bgStr = copyLoginFile(bgStr);
        }
    } else if (!status) {
        bgStr = "";
    }
    lockSetting->beginGroup("ScreenLock");
    lockSetting->setValue("lockStatus", status);
    lockSetting->endGroup();

    lockLoginSettings->beginGroup("greeter");
    lockLoginSettings->setValue("backgroundPath", bgStr);
    lockLoginSettings->endGroup();
}

bool Screenlock::getLockStatus()
{
    if (!QFile::exists(mUKCConfig)) {
        setLockBackground(true);
    }

    lockSetting->beginGroup("ScreenLock");
    lockSetting->sync();
    bool status = lockSetting->value("lockStatus").toBool();
    lockSetting->endGroup();
    return  status;
}

void Screenlock::connectToServer()
{
    QThread *NetThread = new QThread;
    MThread *NetWorker = new MThread;
    NetWorker->moveToThread(NetThread);
    connect(NetThread, &QThread::started, NetWorker, &MThread::run);
    connect(NetWorker,&MThread::keychangedsignal,this,&Screenlock::keyChangedSlot);
    connect(NetThread, &QThread::finished, NetWorker, &MThread::deleteLater);
     NetThread->start();
}

void Screenlock::keyChangedSlot(const QString &key)
{
    if(key == "ukui-screensaver") {
        if(!bIsCloudService)
            bIsCloudService = true;
        QString bgStr = "";
        if (lSetting->keys().contains(SCREENLOCK_BG_KEY))
            bgStr = lSetting->get(SCREENLOCK_BG_KEY).toString();
        if (bgStr.isEmpty()) {
            if (QGSettings::isSchemaInstalled(MATE_BACKGROUND_SCHEMAS)) {
                QGSettings * bgGsetting  = new QGSettings(MATE_BACKGROUND_SCHEMAS, QByteArray(), this);
                if (bgGsetting->keys().contains("pictureFilename"))
                    bgStr = bgGsetting->get(FILENAME).toString();
            }
        }

        ui->previewLabel->setPixmap(QPixmap(bgStr).scaled(ui->previewLabel->size()));
        QStringList keys =  lSetting->keys();
        if (keys.contains("lockEnabled")) {
            bool status = lSetting->get(SCREENLOCK_LOCK_KEY).toBool();
            lockSwitchBtn->setChecked(status);
        }
        loginbgSwitchBtn->setChecked(getLockStatus());
    }
}

void Screenlock::setScreenLockBgSlot()
{
    QStringList filters;
    filters<<tr("Wallpaper files(*.jpg *.jpeg *.bmp *.dib *.png *.jfif *.jpe *.gif *.tif *.tiff *.wdp)");
    QFileDialog fd(pluginWidget);

    QList<QUrl> usb_list = fd.sidebarUrls();
    int sidebarNum = 8;// 最大添加U盘数，可以自己定义
    QString home_path = QDir::homePath().section("/", -1, -1);
    QString mnt = "/media/" + home_path + "/";
    QDir mntDir(mnt);
    mntDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
    QFileInfoList file_list = mntDir.entryInfoList();
    QList<QUrl> mntUrlList;
    for (int i = 0; i < sidebarNum && i < file_list.size(); ++i) {
        QFileInfo fi = file_list.at(i);
        mntUrlList << QUrl("file://" + fi.filePath());
    }

    QFileSystemWatcher m_fileSystemWatcher(&fd);
    m_fileSystemWatcher.addPath("/media/" + home_path + "/");
    connect(&m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged, &fd,
            [=, &sidebarNum, &mntUrlList, &usb_list, &fd](const QString path) {
        QDir m_wmntDir(path);
        m_wmntDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
        QFileInfoList m_wfilist = m_wmntDir.entryInfoList();
        mntUrlList.clear();
        for (int i = 0; i < sidebarNum && i < m_wfilist.size(); ++i) {
            QFileInfo m_fi = m_wfilist.at(i);
            mntUrlList << QUrl("file://" + m_fi.filePath());
        }
        fd.setSidebarUrls(usb_list + mntUrlList);
        fd.update();
    });

    connect(&fd, &QFileDialog::finished, &fd, [=, &usb_list, &fd]() {
        fd.setSidebarUrls(usb_list);
    });


    fd.setDirectory(QString(const_cast<char *>(g_get_user_special_dir(G_USER_DIRECTORY_PICTURES))));
    fd.setAcceptMode(QFileDialog::AcceptOpen);
    fd.setViewMode(QFileDialog::List);
    fd.setNameFilters(filters);
    fd.setFileMode(QFileDialog::ExistingFile);
    fd.setWindowTitle(tr("select custom wallpaper file"));
    fd.setLabelText(QFileDialog::Accept, tr("Select"));
    fd.setLabelText(QFileDialog::LookIn, tr("Position: "));
    fd.setLabelText(QFileDialog::FileName, tr("FileName: "));
    fd.setLabelText(QFileDialog::FileType, tr("FileType: "));
    fd.setLabelText(QFileDialog::Reject, tr("Cancel"));

    fd.setSidebarUrls(usb_list + mntUrlList);

    if (fd.exec() != QDialog::Accepted)
        return;
    QString selectedfile;
    selectedfile = fd.selectedFiles().first();

    QStringList fileRes = selectedfile.split("/");

    QProcess * process = new QProcess(this);
    QString program("cp");
    QStringList arguments;
    arguments << selectedfile ;
    arguments << "/tmp";
    process->start(program, arguments);

    lSetting->set(SCREENLOCK_BG_KEY, selectedfile);
    setLockBackground(loginbgSwitchBtn->isChecked());
    if (prePicUnit != nullptr) {  //去掉选定标记
        prePicUnit->changeClickedFlag(false);
        prePicUnit->setStyleSheet("border-width: 0px;");
    }
}

QString Screenlock::copyLoginFile(QString fileName) {
    QString name = qgetenv("USER");
    if (name.isEmpty()) {
        name = qgetenv("USERNAME");
    }
    QString loginFilename = "/var/lib/lightdm-data/" + name + "/" + "loginBackground";
    QString loginCmd = QString("cp '%1' %2").arg(fileName).arg(loginFilename);
    system(loginCmd.toUtf8().data());
    return loginFilename;
}

void Screenlock::resetDefaultScreenLockSlot(){
    GSettings * wpgsettings;
    wpgsettings = g_settings_new(SCREENLOCK_BG_SCHEMA);
    GVariant * variant = g_settings_get_default_value(wpgsettings, SCREENLOCK_BG_KEY);
    gsize size = g_variant_get_size(variant);
    const char * dwp = g_variant_get_string(variant, &size);
    g_object_unref(wpgsettings);
    lSetting->set(SCREENLOCK_BG_KEY, QVariant(QString(dwp)));
    setClickedPic(QString(dwp));
    setLockBackground(loginbgSwitchBtn->isChecked());
}

void Screenlock::setClickedPic(QString fileName) {
    if (fileName == DEFAULT_LOCK_2) {
        fileName = DEFAULT_LOCK;
    }
    for (int i = flowLayout->count() - 1; i >= 0; --i) {
        QLayoutItem *it      = flowLayout->itemAt(i);
        PictureUnit *picUnit = static_cast<PictureUnit*>(it->widget());
        if (fileName == picUnit->filenameText()) {
            if (prePicUnit != nullptr) {
                prePicUnit->changeClickedFlag(false);
                prePicUnit->setStyleSheet("border-width: 0px;");
            }
            picUnit->changeClickedFlag(true);
            prePicUnit = picUnit;
            picUnit->setFrameShape(QFrame::Box);
            picUnit->setStyleSheet(picUnit->clickedStyleSheet);
        }
    }
}

void Screenlock::settingForIntel()
{
    ui->loginpicLabel->setVisible(false);
    ui->line->setVisible(false);
    if (loginbgSwitchBtn) {
        loginbgSwitchBtn->setVisible(false);
    }

    ui->showMsgLabel->setVisible(true);
    showMsgBtn->setVisible(true);
    ui->line_4->setVisible(true);
    ui->onlineBtn->setVisible(false);
    ui->browserLocalwpBtn->setFixedHeight(48);
    ui->resetBtn->setFixedHeight(48);
}
